package com.demo.test.juc.Atomic;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * CAS是英文单词Compare and Swap的缩写，翻译过来就是比较并替换。
 *
 * CAS机制中使用了3个基本操作数：内存地址V，旧的预期值A，要修改的新值B。更新一个变量的时候，
 * 只有当变量的预期值A和内存地址V当中的实际值相同时，才会将内存地址V对应的值修改为B。
 *
 * 在sun.misc.Unsafe中提供了CAS操作的本地方法。
 * ————————————————
 * 版权声明：本文为CSDN博主「1 + 1=王」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
 * 原文链接：https://blog.csdn.net/weixin_43598687/article/details/122652255
 */
public class IaddTest2 {

    public int i = 0;
    private static Unsafe unsafe;
    private static long fieldOffset;

    static {
        try {
            // 通过反射获取theUnsafe属性
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            // theUnsafe是private的，设置setAccessible(true)
            field.setAccessible(true);
            // 获取Unsafe对象
            unsafe = (Unsafe) field.get(null);

            // 获取属性i在内存中的实际地址
            fieldOffset = unsafe.objectFieldOffset(IaddTest2.class.getField("i"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void add(){
        int current;
        do {
            current = unsafe.getIntVolatile(this,fieldOffset);
        }while (!unsafe.compareAndSwapInt(this,fieldOffset,i,i+1));
    }

    public static void main(String[] args) throws Exception {
        IaddTest2 iaddTest = new IaddTest2();

        for(int i=0;i<2;i++){       //创建两个线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i=0;i<10000;i++){
                        iaddTest.add();
                    }
                }
            }).start();
        }

        Thread.sleep(2000L);//sleep两秒，等待两个线程任务全部执行完成
        System.out.println("i:" + iaddTest.i);
    }
}
